#include "haval.h"

CanTxMsg mHavalStream =
{
    0x7e0, 0x18db33f1,
    CAN_ID_STD, CAN_RTR_DATA,
    8,
    0x03, 0x22, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
};

CanTxMsg mHavalBcmStream =
{
    0x765, 0x18db33f1,
    CAN_ID_STD, CAN_RTR_DATA,
    8,
    0x03, 0x22, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00
};

CanTxMsg mHavalIpcStream =
{
    0x721, 0x18db33f1,
    CAN_ID_STD, CAN_RTR_DATA,
    8,
    0x03, 0x22, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00
};


PidMap mHavalPidMap[ENG_DATA_SIZE] =
{
    { ENG_DATA_RPM,           0x04, 0x04, 2, SUPPORTED },
    { ENG_DATA_VS,            0x08, 0x04, 2, SUPPORTED },
    { ENG_DATA_ECT,           0x2f, 0x04, 1, SUPPORTED },
    { ENG_DATA_IAT,           0x0d, 0x04, 1, SUPPORTED },
    { ENG_DATA_APP,           0x00, 3, 1, UNSUPPORTED },
    { ENG_DATA_TP,            0x0b, 0x04, 2, SUPPORTED },
    { ENG_DATA_ERT,           0x00, 3, 1, UNSUPPORTED },
    { ENG_DATA_LOAD,          0x1e, 0x04, 1, SUPPORTED },
    { ENG_DATA_BATTVOLT,      0x0a, 0x04, 2, SUPPORTED },
    { ENG_DATA_REALFUELCO,    0x11, 0x04, 2, UNSUPPORTED },
    { ENG_DATA_FUELLEVEL,     0x11, 0x04, 2, UNSUPPORTED },
    { ENG_DATA_ODO,           0x11, 0x04, 2, UNSUPPORTED },
    { ENG_DATA_LTFT,          0x74, 0x09, 2, UNSUPPORTED },
    { ENG_DATA_STFT,          0x74, 0x06, 2, UNSUPPORTED },
    { ENG_DATA_MISFIRE1,      0x0f, 0x03, 2, UNSUPPORTED },
    { ENG_DATA_MISFIRE2,      0x0f, 0x06, 2, UNSUPPORTED },
    { ENG_DATA_MISFIRE3,      0x0f, 0x09, 2, UNSUPPORTED },
    { ENG_DATA_MISFIRE4,      0x10, 0x03, 2, UNSUPPORTED },
    { ENG_DATA_MISFIRE5,      0x00, 3, 1, UNSUPPORTED },
    { ENG_DATA_MISFIRE6,      0x00, 3, 1, UNSUPPORTED },
    { ENG_DATA_FCLS,          0x00, 3, 1, UNSUPPORTED },
    { ENG_DATA_KEYSTATUS,     0x00, 3, 1, UNSUPPORTED },
    { ENG_DATA_HO2S1,         0x00, 3, 1, UNSUPPORTED },
    { ENG_DATA_HO2S2,         0x00, 3, 1, UNSUPPORTED },
    { ENG_DATA_MAP,           0x45, 4, 2, SUPPORTED },
    { ENG_DATA_INJECTPULSE,   0x00, 3, 1, UNSUPPORTED },
    { ENG_DATA_OILPRESSURE,   0x00, 3, 1, UNSUPPORTED },
    { ENG_DATA_OILLEVELSTATUS,0x00, 3, 1, UNSUPPORTED },
};

PidMap mHavalBcmPidMap[BCM_DATA_SIZE] =
{
    {BCM_DATA_LFWIN,          0x00, 0x04, 0x01, UNSUPPORTED},
    {BCM_DATA_RFWIN,          0x00, 0x04, 0x01, UNSUPPORTED},
    {BCM_DATA_LRWIN,          0x00, 0X05, 0X01, UNSUPPORTED},
    {BCM_DATA_RRWIN,          0x00, 0x05, 0x01, UNSUPPORTED},
    {BCM_DATA_DDA,            0x07, 0x04, 0x01, SUPPORTED},
    {BCM_DATA_PDA,            0x07, 0x04, 0x01, SUPPORTED},
    {BCM_DATA_RRDA,           0x07, 0x04, 0x01, SUPPORTED},
    {BCM_DATA_LRDA,           0x07, 0x04, 0x01, SUPPORTED},
    {BCM_DATA_SUNROOF,        0x07, 0x04, 0x01, UNSUPPORTED},
    {BCM_DATA_PARKLAMP,       0x07, 0x04, 0x01, UNSUPPORTED},
    {BCM_DATA_HEADLAMP,       0x07, 0x04, 0x01, UNSUPPORTED},
    {BCM_DATA_CHARGESTATUS,   0x07, 0x04, 0x01, UNSUPPORTED},
    {BCM_DATA_BATTCURRENT,    0x07, 0x04, 0x01, UNSUPPORTED},
    {BCM_DATA_BATTSTATUS,     0x07, 0x04, 0x01, UNSUPPORTED},
    {BCM_DATA_BATTVOLT,       0x07, 0x04, 0x01, UNSUPPORTED},
    {BCM_DATA_ODO,            0x07, 0x04, 0x01, UNSUPPORTED},
};

PidMap mHavalIpcPidMap[IPC_DATA_SIZE] =
{
    { IPC_DATA_REALFUELCO,    0x98, 0x04, 2, UNSUPPORTED },
    { IPC_DATA_ODO,           0x05, 0x04, 2, SUPPORTED },
    { IPC_DATA_FUELLEVEL,     0x06, 0x04, 1, UNSUPPORTED },
};

VehicleProcessOps mHavalProcessOps;

void haval_init(Vehicle *vehicle)
{
    logi("%s", __func__);
    mHavalProcessOps.check_engine_on = haval_check_engine_on;
    mHavalProcessOps.get_rpm = haval_get_rpm;
    mHavalProcessOps.process_vin_code = haval_process_vin_code;
    mHavalProcessOps.process_eng_data = haval_process_eng_data;
    mHavalProcessOps.process_bcm_data = haval_process_bcm_data;
    mHavalProcessOps.process_ipc_data = haval_process_ipc_data;

    vehicle->processOps = &mHavalProcessOps;

    bsp_can_filter(0x7e8, 0x7e8, 0x7ff, 0x7ff);
}

//haval data functions
uint8_t haval_check_engine_on(void)
{
    //uint8_t i = 0;
    uint8_t on = FALSE;
    CanRxMsg rxMsg;

    //rpm pid
    mHavalStream.Data[3] = 0x04;
    bsp_can_clear();
    bsp_can_filter(0x7e8, 0x7e8, 0x7ff, 0x7ff);
    if(vehicle_can_session(&mHavalStream, &rxMsg)) {
        on = TRUE;
    } else {
        on = FALSE;
    }
    return on;
}

void haval_get_rpm(uint16_t *rpm)
{
    CanRxMsg rxMsg;

    //rpm pid
    mHavalStream.Data[3] = 0x04;
    bsp_can_clear();
    bsp_can_filter(0x7e8, 0x7e8, 0x7ff, 0x7ff);
    if(vehicle_can_session(&mHavalStream, &rxMsg)) {
        *rpm = (rxMsg.Data[4] << 8) | rxMsg.Data[5];
    } else {
        *rpm = 0;
    }
}

void haval_process_vin_code(VinCode *code)
{
    uint8_t i, j, k;
    uint8_t ret;
    CanRxMsg rxMsg;
    uint8_t offset;
    uint8_t size;
    uint8_t pid;
    uint8_t first;
    uint8_t second;
    uint16_t index;
    uint16_t buf_index;
    uint8_t temp_buf[128];
    uint8_t package_count = 0;
    uint8_t bytes = 0;
    uint8_t sub_off;
    uint8_t index_of_pid;
    CanTxMsg vinPackage =
    {
        0x7df, 0x18db33f1,
        CAN_ID_STD, CAN_RTR_DATA,
        8,
        0x03, 0x22, 0xf1, 0x90, 0x00, 0x00, 0x00, 0x00
    };
    CanTxMsg continuePackage =
    {
        0x7df, 0x18db33f1,
        CAN_ID_STD, CAN_RTR_DATA,
        8,
        0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };

    logi("%s", __func__);
    bsp_can_clear();
    bsp_can_filter(0x7e8, 0x7e8, 0x7ff, 0x7ff);
    //check the pid is supported
    size = 17;
    offset = 5;
    //send data stream
    buf_index = 0;
    memset(temp_buf, 0x00, 128);
    ret = vehicle_can_session(&vinPackage, &rxMsg);
    if(ret) {
        first = rxMsg.Data[0];
        second = rxMsg.Data[1];
        index = index_of_buf(rxMsg.Data, 8, pid);
        if(first == 0x10) {
            //long package
            bytes = rxMsg.Data[1];
            package_count = (bytes - 6) / 7;
            if((bytes - 6) % 7 > 0) {
                package_count ++;
            }
            for(j = index + 1; j < 8; j++) {
                temp_buf[buf_index ++] = rxMsg.Data[j];
            }
            //send continue package
            bsp_can_send(&continuePackage);
            for(j = 0; j < package_count; j++) {
                ret = vehicle_can_recv(&rxMsg);
                if(ret) {
                    for(k = 1; k < 8; k++) {
                        temp_buf[buf_index ++] = rxMsg.Data[k];
                    }
                } else {
                    break;
                }
            }
        } else if(first != 0x10 && second == 0x61){
            //short package
            for(j = index + 1; j < 8; j++) {
                temp_buf[buf_index ++] = rxMsg.Data[j];
            }
        } else {
            //error
            return;
        }

        code->updated = TRUE;
        memcpy(code->code, temp_buf + offset, size);
        logi("vin: ");
        for(i = 0; i < 17; i++) {
            printf("%02x ", code->code[i]);
        }
        printf("\r\n");
    } else {
        return;
    }
    os_delay_ms(100);
}

void haval_process_eng_data(EngineDataMap *dataMap)
{
    uint8_t i;
    uint8_t support;
    uint8_t pid;
    uint8_t offset;
    uint8_t size;
    CanRxMsg rxMsg;

    bsp_can_clear();
    bsp_can_filter(0x7e8, 0x7e8, 0x7ff, 0x7ff);
    for(i = 0; i < ENG_DATA_SIZE; i++) {
        os_delay_ms(100);
        vehicle_lock();
        support = mHavalPidMap[i].support;
        //check wether this id is supported?
        if(support == UNSUPPORTED) {
            vehicle_unlock();
            continue;
        }
        pid = mHavalPidMap[i].pid;
        offset = mHavalPidMap[i].offset;
        size = mHavalPidMap[i].size;
        mHavalStream.Data[3] = pid;
        //send stream msg
        if(vehicle_can_session(&mHavalStream, &rxMsg)) {
            dataMap->data[i].id = i;
            dataMap->data[i].updated = TRUE;
            dataMap->data[i].len = size;
            memcpy(dataMap->data[i].data, rxMsg.Data + offset, size);
        }
        vehicle_unlock();
    }
}

void haval_process_bcm_data(BcmDataMap *dataMap)
{
    uint8_t i;
    uint8_t support;
    uint8_t pid;
    uint8_t offset;
    uint8_t size;
    CanRxMsg rxMsg;

    bsp_can_clear();
    bsp_can_filter(0x7a5, 0x7a5, 0x7ff, 0x7ff);
    for(i = 0; i < BCM_DATA_SIZE; i++) {
        os_delay_ms(100);
        vehicle_lock();
        support = mHavalBcmPidMap[i].support;
        //check wether this id is supported?
        if(support == UNSUPPORTED) {
            vehicle_unlock();
            continue;
        }
        pid = mHavalBcmPidMap[i].pid;
        offset = mHavalBcmPidMap[i].offset;
        size = mHavalBcmPidMap[i].size;
        mHavalBcmStream.Data[3] = pid;
        //send stream msg
        if(vehicle_can_session(&mHavalBcmStream, &rxMsg)) {
            dataMap->data[i].id = i;
            dataMap->data[i].updated = TRUE;
            dataMap->data[i].len = size;
            memcpy(dataMap->data[i].data, rxMsg.Data + offset, size);
        }
        vehicle_unlock();
    }
}

void haval_process_ipc_data(IpcDataMap *dataMap)
{
    uint8_t i;
    uint8_t support;
    uint8_t pid;
    uint8_t offset;
    uint8_t size;
    CanRxMsg rxMsg;

    bsp_can_clear();
    bsp_can_filter(0x729, 0x729, 0x7ff, 0x7ff);
    for(i = 0; i < IPC_DATA_SIZE; i++) {
        os_delay_ms(100);
        vehicle_lock();
        support = mHavalIpcPidMap[i].support;
        //check wether this id is supported?
        if(support == UNSUPPORTED) {
            vehicle_unlock();
            continue;
        }
        pid = mHavalIpcPidMap[i].pid;
        offset = mHavalIpcPidMap[i].offset;
        size = mHavalIpcPidMap[i].size;
        mHavalIpcStream.Data[3] = pid;
        //send stream msg
        if(vehicle_can_session(&mHavalIpcStream, &rxMsg)) {
            dataMap->data[i].id = i;
            dataMap->data[i].updated = TRUE;
            dataMap->data[i].len = size;
            memcpy(dataMap->data[i].data, rxMsg.Data + offset, size);
        }
        vehicle_unlock();
    }
}

